[IA64] Add glue code for VTD
authorIsaku Yamahata <yamahata@valinux.co.jp>
Fri, 24 Oct 2008 04:49:58 +0000 (13:49 +0900)
committerIsaku Yamahata <yamahata@valinux.co.jp>
Fri, 24 Oct 2008 04:49:58 +0000 (13:49 +0900)
Signed-off-by: Anthony Xu <anthony.xu@intel.com>
xen/arch/ia64/linux-xen/acpi.c
xen/arch/ia64/vmx/viosapic.c
xen/arch/ia64/vmx/vmx_fault.c
xen/arch/ia64/xen/domain.c
xen/arch/ia64/xen/irq.c
xen/arch/ia64/xen/mm.c
xen/include/asm-ia64/linux-xen/asm/acpi.h
xen/include/asm-ia64/linux-xen/asm/iosapic.h
xen/include/asm-ia64/viosapic.h

index 97ad0bbcc57c3b27cd8c5280a96780abafd53ddd..cc6ac3575ad173b2b01efbec732be7f6f028c213 100644 (file)
@@ -797,6 +797,10 @@ int __init acpi_boot_init(void)
        if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt))
                printk(KERN_ERR PREFIX "Can't find FADT\n");
 
+#ifdef XEN
+       acpi_dmar_init();
+#endif
+
 #ifdef CONFIG_SMP
        if (available_cpus == 0) {
                printk(KERN_INFO "ACPI: Found 0 CPUS; assuming 1\n");
index cf3bf9955dc58f2c9299992e55e72012bfeabb0b..8922fbe2dc3b242134b88a3a55773f3248116161 100644 (file)
@@ -121,6 +121,13 @@ static void viosapic_update_EOI(struct viosapic *viosapic, int vector)
                      redir_num, vector);
         return;
     }
+    if ( iommu_enabled )
+    {
+        spin_unlock(&viosapic->lock);
+        hvm_dpci_eoi(current->domain, redir_num, &viosapic->redirtbl[redir_num]);
+        spin_lock(&viosapic->lock);
+    }
+
     service_iosapic(viosapic);
     spin_unlock(&viosapic->lock);
 }
index 5a6ed0a163685a72a2a57cb1912ec329f42f39a0..e1365aa4a05cbd73c94a4b4be4ed2951b7e3b764 100644 (file)
@@ -54,6 +54,7 @@
 #include <asm/shadow.h>
 #include <asm/sioemu.h>
 #include <public/arch-ia64/sioemu.h>
+#include <xen/hvm/irq.h>
 
 /* reset all PSR field to 0, except up,mfl,mfh,pk,dt,rt,mc,it */
 #define INITIAL_PSR_VALUE_AT_INTERRUPTION 0x0000001808028034
@@ -306,6 +307,7 @@ void leave_hypervisor_tail(void)
                 viosapic_set_irq(d, callback_irq, 0);
             }
         }
+        hvm_dirq_assist(v);
     }
 
     rmb();
index 679d0c3a9a0b902fba4c383818138c3b87678f09..68b243a9dee98672c4273b1e7dbf948f0352a342 100644 (file)
@@ -602,6 +602,11 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
        if ((d->arch.mm.pgd = pgd_alloc(&d->arch.mm)) == NULL)
            goto fail_nomem;
 
+       if ( iommu_enabled && (is_hvm_domain(d) || need_iommu(d)) ){
+               if(iommu_domain_init(d) != 0)
+                       goto fail_iommu;
+       }
+
        /*
         * grant_table_create() can't fully initialize grant table for domain
         * because it is called before arch_domain_create().
@@ -618,6 +623,8 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
        dprintk(XENLOG_DEBUG, "arch_domain_create: domain=%p\n", d);
        return 0;
 
+fail_iommu:
+       iommu_domain_destroy(d);
 fail_nomem:
        tlb_track_destroy(d);
 fail_nomem1:
@@ -637,6 +644,11 @@ void arch_domain_destroy(struct domain *d)
                free_xenheap_pages(d->shared_info,
                                   get_order_from_shift(XSI_SHIFT));
 
+       if ( iommu_enabled && (is_hvm_domain(d) || need_iommu(d)) )     {
+               pci_release_devices(d);
+               iommu_domain_destroy(d);
+       }
+
        tlb_track_destroy(d);
 
        /* Clear vTLB for the next domain.  */
index 2c250148c52b7cedcb94bbba9e14f8d05a257c41..e3c3da3b08b973ad8541ad120feca356fb5f69be 100644 (file)
@@ -312,12 +312,25 @@ typedef struct {
     struct domain *guest[IRQ_MAX_GUESTS];
 } irq_guest_action_t;
 
+static struct timer irq_guest_eoi_timer[NR_IRQS];
+static void irq_guest_eoi_timer_fn(void *data)
+{
+       irq_desc_t *desc = data;
+       unsigned vector = desc - irq_desc;
+       unsigned long flags;
+
+       spin_lock_irqsave(&desc->lock, flags);
+       desc->status &= ~IRQ_INPROGRESS;
+       desc->handler->enable(vector);
+       spin_unlock_irqrestore(&desc->lock, flags);
+}
+
 void __do_IRQ_guest(int irq)
 {
     irq_desc_t         *desc = &irq_desc[irq];
     irq_guest_action_t *action = (irq_guest_action_t *)desc->action;
     struct domain      *d;
-    int                 i;
+    int                 i, already_pending = 0;
 
     for ( i = 0; i < action->nr_guests; i++ )
     {
@@ -325,8 +338,29 @@ void __do_IRQ_guest(int irq)
         if ( (action->ack_type != ACKTYPE_NONE) &&
              !test_and_set_bit(irq, &d->pirq_mask) )
             action->in_flight++;
-        send_guest_pirq(d, irq);
-    }
+               if ( hvm_do_IRQ_dpci(d, irq) )
+               {
+                       if ( action->ack_type == ACKTYPE_NONE )
+                       {
+                               already_pending += !!(desc->status & IRQ_INPROGRESS);
+                               desc->status |= IRQ_INPROGRESS; /* cleared during hvm eoi */
+                       }
+               }
+               else if ( send_guest_pirq(d, irq) &&
+                               (action->ack_type == ACKTYPE_NONE) )
+               {
+                       already_pending++;
+               }
+       }
+
+       if ( already_pending == action->nr_guests )
+       {
+               desc->handler->disable(irq);
+               stop_timer(&irq_guest_eoi_timer[irq]);
+               init_timer(&irq_guest_eoi_timer[irq],
+                               irq_guest_eoi_timer_fn, desc, smp_processor_id());
+               set_timer(&irq_guest_eoi_timer[irq], NOW() + MILLISECS(1));
+       }
 }
 
 int pirq_acktype(int irq)
index 9cf861f5eb47a26c217808189b4177623bc9ecd0..0ccd756046ffa25190bddcf3dd28c064abe750d8 100644 (file)
@@ -1435,6 +1435,8 @@ zap_domain_page_one(struct domain *d, unsigned long mpaddr,
     if (mfn == INVALID_MFN) {
         // clear pte
         old_pte = ptep_get_and_clear(mm, mpaddr, pte);
+        if(!pte_mem(old_pte))
+            return;
         mfn = pte_pfn(old_pte);
     } else {
         unsigned long old_arflags;
@@ -1472,6 +1474,13 @@ zap_domain_page_one(struct domain *d, unsigned long mpaddr,
     if(!mfn_valid(mfn))
         return;
 
+    if ( iommu_enabled && (is_hvm_domain(d) || need_iommu(d)) ){
+        int i, j;
+        j = 1 << (PAGE_SHIFT-PAGE_SHIFT_4K);
+        for(i = 0 ; i < j; i++)
+            iommu_unmap_page(d, (mpaddr>>PAGE_SHIFT)*j + i);
+    }
+
     page = mfn_to_page(mfn);
     BUG_ON((page->count_info & PGC_count_mask) == 0);
 
@@ -2856,6 +2865,12 @@ __guest_physmap_add_page(struct domain *d, unsigned long gpfn,
     smp_mb();
     assign_domain_page_replace(d, gpfn << PAGE_SHIFT, mfn,
                                ASSIGN_writable | ASSIGN_pgc_allocated);
+    if ( iommu_enabled && (is_hvm_domain(d) || need_iommu(d)) ){
+        int i, j;
+        j = 1 << (PAGE_SHIFT-PAGE_SHIFT_4K);
+        for(i = 0 ; i < j; i++)
+            iommu_map_page(d, gpfn*j + i, mfn*j + i);
+    }
 }
 
 int
index f59db9202e02e73910c1228364d5db7ce923b696..7a66a0c12415e8674d5a1d7bc85e3798adca2a44 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/numa.h>
 #ifdef XEN
 #include <xen/nodemask.h>
+extern int acpi_dmar_init(void);
 #endif
 
 #define COMPILER_DEPENDENT_INT64       long
index d3d68ef08268002ae46507594f1790c16247b19b..46dd30ec53e15787d13e146334f6d0a0ca9de830 100644 (file)
@@ -83,12 +83,25 @@ static inline int find_iosapic_by_addr(unsigned long addr)
 
 static inline unsigned int iosapic_read(char __iomem *iosapic, unsigned int reg)
 {
+#ifdef XEN
+       if(iommu_enabled && (reg >= 10)){
+               int apic = find_iosapic_by_addr((unsigned long)iosapic);
+               return io_apic_read_remap_rte(apic, reg);
+       }
+#endif
        writel(reg, iosapic + IOSAPIC_REG_SELECT);
        return readl(iosapic + IOSAPIC_WINDOW);
 }
 
 static inline void iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
 {
+#ifdef XEN
+       if (iommu_enabled && (reg >= 10)){
+               int apic = find_iosapic_by_addr((unsigned long)iosapic);
+               iommu_update_ire_from_apic(apic, reg, val);
+               return;
+       }
+#endif
        writel(reg, iosapic + IOSAPIC_REG_SELECT);
        writel(val, iosapic + IOSAPIC_WINDOW);
 }
index c334ea0c60be5ad5390101e336c0c8fb77ef7623..7004e6e5b9d725a4b5d46550a8b3c290f5809d4f 100644 (file)
@@ -70,5 +70,7 @@ void viosapic_write(struct vcpu *v, unsigned long addr,
 
 unsigned long viosapic_read(struct vcpu *v, unsigned long addr,
                             unsigned long length);
+void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
+                          union vioapic_redir_entry *ent);
 
 #endif /* __ASM_IA64_VMX_VIOSAPIC_H__ */